<template>
	<view class="flow-measurement">
		<u-navbar :title="duopultit" @rightClick="rightClick" :autoBack="true" rightIcon="setting-fill" placeholder
			bgColor="#f0f5ff">

		</u-navbar>
		<!-- 统计数据展示 -->
		<view class="card stats-card">
			<view class="stats-row">
				<view class="stat-item">
					<view class="stat-value">{{ instantaneousFlow }}</view>
					<view class="stat-label">瞬时流速</view>
				</view>
				<view class="stat-item">
					<view class="stat-value">{{ uniformity }}</view>
					<view class="stat-label">均匀度</view>
				</view>
			</view>

			<view class="stats-row">
				<view class="stat-item">
					<view class="stat-value">{{ maxFlow }}</view>
					<view class="stat-label">平均流速</view>
				</view>
				<view class="stat-item">
					<!-- <view class="stat-value">{{ minFlow }}</view> -->
					<view class="stat-value">{{ this.calculateFlow(this.maxFlow) }}</view>
					<view class="stat-label">流量</view>
				</view>
			</view>
		</view>

		<!-- 流速柱状图 -->
		<view class=" chart-card">
			<!-- <view class="" :class="isActive?'yuan_b':'yuan_c'">流速</view> -->
			<view class="chart-container">
				<flowbarchart ref="flowChart" :chartData="flowChartData" />
			</view>
		</view>

		<!-- 均匀度曲线图 -->
		<view class="chart-card">
			<!-- <view class="" :class="isActive?'yuan_b':'yuan_c'">流量</view> -->
			<view class="chart-container">
				<flowlechart ref="mitychart" :chartData="scatteredPoints" />
			</view>
		</view>
		<!-- 状态指示 -->
		<view class="status-indicator" :class="{ active: measuring }">
			<text class="status-dot"></text>
			<text class="status-text">{{ measuring ? '测量中...' : '已停止' }}</text>
		</view>
		<!-- 按钮区域 -->
		<view class="button-container">
			<view class="button-row">
				<view class="btn btn-start" @tap="startMeasuring">
					<text class="btn-text">开始测量</text>
					<text class="btn-icon">▶</text>
				</view>
				<view class="btn btn-stop" @tap="stopMeasuring">
					<text class="btn-text">结束测量</text>
					<text class="btn-icon">⏹</text>
				</view>
			</view>

			<view class="button-row">
				<view class="btn btn-clear" @tap="clearData">
					<text class="btn-text">清空数据</text>
					<text class="btn-icon">↺</text>
				</view>
			</view>
		</view>
		<!-- 弹窗 -->
		<!-- 提示窗示例 -->
		<uni-popup ref="alertDialog" type="dialog">
			<uni-popup-dialog type="success" cancelText="关闭" confirmText="确定" title="设置" @confirm="dialogConfirm"
				@close="dialogClose">
				<view class="popbox">
					<view class="popit">
						<view class="tex">
							连接设备：
						</view>
						<view class="inpa" @click="tobelFn" v-if="lanname == ''">
							点击连接设备
						</view>
						<view class="inpb" @click="lampRFn" v-if="lanname != ''">
							点击断开设备
						</view>
					</view>
					<view class="popit">
						<view class="tex">
							选择品牌：
						</view>
						<view class="bga">
							<uni-data-select v-model="dopBrand" :localdata="range" :clear="false"
								@change="changevalue"></uni-data-select>
						</view>
					</view>
					<view class="popit">
						<view class="tex">
							流速系数：
						</view>
						<view class="bga">
							<uni-easyinput v-model="xishu" placeholder="请输入内容" type="digit" :clearable="false"
								@change="changeinp"></uni-easyinput>
						</view>
					</view>
					<view class="popit">
						<view class="tex">
							流量系数：
						</view>
						<view class="bga">
							<uni-easyinput v-model="flowCoefficient" placeholder="请输入内容" type="digit" :clearable="false"
								@change="ficientcoe"></uni-easyinput>
						</view>
					</view>
					<view class="popit">
						<view class="tex">
							设置水深：
						</view>
						<view class="bga">
							<uni-easyinput v-model="wD" placeholder="请输入内容" type="digit"
								:clearable="false"></uni-easyinput>
						</view>
					</view>
				</view>
			</uni-popup-dialog>
		</uni-popup>
		<!-- <button @click="testData">更新数据</button> -->

	</view>
</template>

<script>
	import flowbarchart from './FlowBarChart.vue'
	import flowlechart from './flowLeChart.vue'
	// const SixUniTts = uni.requireNativePlugin("SmallSix-SixUniTts")
	export default {
		components: {
			flowbarchart,
			flowlechart
		},
		data() {
			return {
				deviceId: '', //蓝牙
				serviceId: '', //蓝牙
				characteristicId: '', //蓝牙
				fff: '', //蓝牙
				lanname: '', //蓝牙名称json
				instantaneousFlow: 0.0, // 瞬时流速值，单位L/s
				uniformity: 0, // 均匀度百分比
				maxFlow: 0, // 最大流速值
				minFlow: 0, // 最小流速值
				measuring: false, // 测量状态标识
				measureInterval: null, // 测量定时器引用
				flowChartData: {
					categories: [],
					series: [{
						name: "流速",
						data: []
					}, {
						name: "水深",
						data: []
					}]
				},
				newData: {
					categories: [],
					series: [{
						name: "流速",
						data: []
					}, {
						name: "水深",
						data: []
					}]
				},
				scatteredPoints: {
					categories: [],
					series: [{
						name: "流量",
						data: []
					}]
				},
				inlineArr: [], //均匀度
				range: [{
						value: '泰克',
						text: "泰克"
					},
					{
						value: '大禹',
						text: "大禹"
					},
					{
						value: '睿鑫',
						text: "睿鑫"
					},
					{
						value: '德希',
						text: "德希"
					}
				],
				flowCoefficient: 1, //流量系数
				xishu: 1, //系数
				dopBrand: '', //品牌
				isActive: false, //信号灯闪烁
				junyundArr: [], //计算均匀度
				interceptArr: [], //截取流速
				duopultit: '未连接设备',
				cezhanObj: {}, //测站信息
				wD: 0, //水深
				trafficIcon: [] // 流量
			};
		},
		onShow() {
			//弹窗设置
			// if (this.$refs.alertDialog) {
			// 	this.$refs.alertDialog.close()
			// }
			let obj = this.vuex_dopplerFlowmeter //设置
			this.xishu = obj.xishu //设置
			this.flowCoefficient = obj.flowCoefficient //设置
			this.dopBrand = obj.dopBrand //设置
			this.wD = obj.wD //设置
			this.lanname = this.vuex_devicename //蓝牙
			this.deviceId = this.vuex_deviceId //蓝牙
			this.getBLEDeviceServices() //蓝牙服务
			if (this.lanname != '') {
				this.duopultit = '设备已连接'
			} else {
				this.duopultit = '未连接设备'
			}
			uni.showLoading({
				mask: true,
				title: '连接设备中...'
			});
			setTimeout(() => {
				uni.hideLoading()
			}, 3000)
			// 处理数据
			this.dataFormat()
			// 断开设备
			uni.onBLEConnectionStateChange((res) => {
				// 该方法回调中可以用于处理连接意外断开等异常情况
				if (res.connected !== true) {
					console.log('意外断开');
					this.lanname = ''
					this.duopultit = '未连接设备'
					uni.$u.vuex('vuex_devicename', '')
					uni.$u.vuex('vuex_deviceId', '')
				}
			})
		},
		methods: {
			// 测试数据图表
			// 下拉品牌
			changevalue(e) {
				console.log('e', e);
				this.dopBrand = e
			},
			// 输入系数
			changeinp(e) {
				console.log('e', e);
				this.xishu = e
			},
			// 输入流量系数
			ficientcoe(e) {
				console.log('e', e);
				this.flowCoefficient = e
			},
			// 设置
			// 确定
			dialogConfirm() {
				let obj = this.vuex_dopplerFlowmeter
				obj.dopBrand = this.dopBrand
				obj.xishu = this.xishu
				obj.flowCoefficient = this.flowCoefficient
				obj.wD = this.wD
				console.log('确定', obj);
				uni.$u.vuex('vuex_dopplerFlowmeter', obj)
			},
			// 取消
			dialogClose() {
				console.log('取消');
			},
			// 直接添加
			addDirectly(data) {
				this.newData.categories.push('') //流速
				this.newData.series[0].data.push(data) //流速
				this.newData.series[0].name = '流速：' + data //流速
				
				this.newData.series[1].data.push(this.wD) //水深
				this.newData.series[1].name = '水深：' + this.wD //水深
				this.flowChartData = this.newData //流速
				// 单独均匀度
				this.junyundArr.push(data)
				// 平均流速
				this.maxFlow = this.averageSum(this.junyundArr).toFixed(3)

				// 流量图标
				this.scatteredPoints.categories.push('') //流量图标
				let liul = (this.calculateFlow(this.maxFlow) * this.flowCoefficient).toFixed(3) * 1
				this.scatteredPoints.series[0].data.push(liul) //流量图标
				this.scatteredPoints.series[0].name = '流量：' +  liul// 流量
				// this.scatteredPoints.series[1].data.push(this.wD) //流量图标

				// 有时候即使重新赋值，也要手动刷新更稳妥
				this.$refs.flowChart.getServerData() //流速分布
				this.$refs.mitychart.getServerData() //均匀度
			},
			//加减替换
			additionAndSubtractionReplacement(data) {
				this.newData.series[0].data.push(data) // 往数组尾部添加数字
				this.newData.series[0].data.shift() // 删除数组最前面的元素
				this.newData.series[0].name = '流速：' + data //流速
				
				this.newData.series[1].data.push(this.wD) // 往数组尾部添加数字
				this.newData.series[1].data.shift() // 删除数组最前面的元素
				this.newData.series[1].name = '水深：' + this.wD //水深
				this.flowChartData = this.newData
				// 流量
				// 流量图标
				console.log('this.maxFlow', this.maxFlow);
				let liul = (this.calculateFlow(this.maxFlow) * this.flowCoefficient).toFixed(3) * 1
				this.scatteredPoints.series[0].data.push(liul) // 往数组尾部添加数字
				this.scatteredPoints.series[0].data.shift() // 删除数组最前面的元素
				this.scatteredPoints.series[0].name = '流量：' +  liul// 流量
				// this.scatteredPoints.series[1].data.push(this.wD) // 往数组尾部添加数字
				// this.scatteredPoints.series[1].data.shift() // 删除数组最前面的元素
				// 均匀度
				// 单独均匀度
				this.junyundArr.push(data)
				this.junyundArr.shift()
				// 平均流速
				this.maxFlow = this.averageSum(this.junyundArr).toFixed(3)
				// 有时候即使重新赋值，也要手动刷新更稳妥
				this.$refs.flowChart.getServerData() //流速分布
				this.$refs.mitychart.getServerData() //均匀度
			},
			// 测试数据
			testData() {
				// 处理数据
				const randomNum = (Math.random() * 0.4 + 0.8).toFixed(3);
				this.mfvFn(randomNum)
			},
			// 接收多普勒数据
			mfvFn(nnub) {
				let data = (nnub * this.xishu).toFixed(3) * 1
				// 直接添加
				console.log('多普勒流速', data);
				this.instantaneousFlow = data //瞬时流速
				let liusyArr = this.junyundArr
				// 均匀度
				if (liusyArr.length >= 1) {
					this.uniformity = this.evennessFn(liusyArr)
				}

				// 平均流速
				// this.maxFlow = this.averageSum(liusyArr).toFixed(3)

				// let nub = Math.random() * 2
				if (this.newData.categories.length <= 59) {
					this.addDirectly(data)
				} else {
					// 加减替换
					this.additionAndSubtractionReplacement(data)
				}

			},
			addNumberAndEmpty(arrNum, arrStr, num) {
				arrNum.push(num); // 往数字数组添加数字 接收数据 
				arrStr.push(''); // 往字符串数组添加空字符串
			},
			// 均匀度数组排序
			processScatterData(originalData) {
				// 深拷贝原始数据，避免修改原数据
				const processedData = JSON.parse(JSON.stringify(originalData));

				// 处理每个series的数据
				processedData.series.forEach(series => {
					// 遍历data数组，重新设置每个点的x坐标为索引值
					series.data = series.data.map((point, index) => {
						return [index, point[1]]; // [索引, 原来的y值]
					});
				});

				return processedData;
			},
			// 均匀度数组
			uniformityFn(data) {
				let arr = data
				let arli = []
				for (let i = 0; i < arr.length; i++) {
					arli[i] = arr[i] * 1000
				}
				// 均匀度
				let x = this.sum(arli) / arli.length
				let y = ''
				let z = []
				for (var i = 0; i < arli.length; i++) {
					y = (x - arli[i]) * (x - arli[i])
					z.push(y)
				}
				let n = this.sum(z) / arli.length
				let m = Math.sqrt(n) / 10
				let j = m.toFixed(0) * 1 //均匀度
				let index = arr.length //数组长度

				let jrr = []
				jrr[0] = index
				jrr[1] = j
				return jrr
			},
			// 均匀度
			evennessFn(data) {
				let arr = data
				let arli = []
				for (let i = 0; i < arr.length; i++) {
					arli[i] = arr[i] * 1000
				}
				// 均匀度
				let x = this.sum(arli) / arli.length
				let y = ''
				let z = []
				for (var i = 0; i < arli.length; i++) {
					y = (x - arli[i]) * (x - arli[i])
					z.push(y)
				}
				let n = this.sum(z) / arli.length
				let m = Math.sqrt(n) / 10

				return m.toFixed(0)

			},
			/**
			 * 开始测量方法
			 * 启动定时器模拟数据采集
			 */
			startMeasuring() {
				if (this.lanname == '') {
					uni.showToast({
						title: '未连接设备！',
						icon: 'none'
					});
					return
				}
				// 如果已经在测量中，则直接返回
				if (this.measuring) return;

				// 更新测量状态
				this.measuring = true;

				// 显示提示消息
				uni.showToast({
					title: '开始测量',
					icon: 'success'
				});
				clearInterval(this.measureInterval);
				// 设置定时器模拟数据更新
				this.measureInterval = setInterval(() => {
					this.inquiryFn()
					console.log(this.measureInterval);
				}, 1000); // 每秒更新一次数据
			},
			// 询问水深
			deepWaterFn(data) {
				// this.wD = data
				console.log('水深', data);
			},
			//询问多普勒
			inquiryFn() {
				// let arr = ['0x04', '0x04', '0x00', '0x00', '0x00', '0x04', '0xF1', '0x9C']

				let arr = []
				if (this.dopBrand == '泰克') {
					arr = ['0x65', '0x03', '0x00', '0x02', '0x00', '0x04', '0xED', '0xED']
				}
				if (this.dopBrand == '大禹') {
					arr = ['0x66', '0x03', '0x00', '0x0C', '0x00', '0x02', '0x0C', '0x1F']

					// arr = ['0x66', '0x03', '0x00', '0x0A', '0x00', '0x02', '0xEC', '0x1E']
				}
				if (this.dopBrand == '睿鑫') {
					arr = ['0x64', '0x03', '0x00', '0x00', '0x00', '0x02', '0xCD', '0xFE']
					// arr = ['0x64', '0x03', '0x00', '0x26', '0x00', '0x02', '0x2C', '0x35']
				}
				if (this.dopBrand == '德希') {
					arr = ['0x04', '0x04', '0x00', '0x00', '0x00', '0x04', '0xF1', '0x9C']
					// arr = ['0x64', '0x03', '0x00', '0x26', '0x00', '0x02', '0x2C', '0x35']
				}
				console.log('输入', arr);
				this.conbuffer(arr) //正式数据
				this.continuityFn() //正式信号灯
			},
			// 信号灯
			continuityFn() {
				if (this.isActive == false) {
					this.music.play_didi()
					this.isActive = true
					setTimeout(() => {
						this.isActive = false
					}, 200)
				}
			},
			/**
			 * 结束测量方法
			 * 清除定时器停止数据采集
			 */
			stopMeasuring() {
				// 如果不在测量中，则直接返回
				if (!this.measuring) return;

				// 更新测量状态
				this.measuring = false;

				// 清除定时器
				clearInterval(this.measureInterval);

				// 显示提示消息
				uni.showToast({
					title: '测量结束',
					icon: 'success'
				});
			},

			/**
			 * 清空数据方法
			 * 重置所有测量数据到初始状态
			 */
			clearData() {
				// 清除定时器
				// clearInterval(this.measureInterval);
				// 重置所有数据
				this.newData.categories = [] //流速
				this.newData.series[0].data = [] //流速
				this.newData.series[1].data = [] //流速
				this.scatteredPoints.categories = [] //均匀度
				this.scatteredPoints.series[0].data = [] //均匀度
				// ---------------页面
				this.instantaneousFlow = 0
				this.uniformity = 0
				this.maxFlow = 0
				this.minFlow = 0
				this.junyundArr = []
				this.interceptArr = []

				// 显示提示消息
				uni.showToast({
					title: '数据已清空',
					icon: 'success'
				});
			},
			// 导航栏
			rightClick() {
				this.$refs.alertDialog.open()
				//在起始页面跳转到test.vue页面并传递参数
				console.log('rightClick');
			},
			leftClick() {
				console.log('leftClick');
			},
			// 蓝牙
			tobelFn() {
				//在起始页面跳转到test.vue页面并传递参数
				uni.navigateTo({
					url: '/pages/index/devBEL'
				});
			},
			//断开连接
			lampRFn() {
				uni.closeBLEConnection({
					deviceId: this.vuex_deviceId,
					success: (res) => {
						uni.showToast({
							title: '设备已断开',
							icon: 'success',
							mask: true,
							duration: 1000
						});
						this.lanname = ''
						uni.$u.vuex('vuex_devicename', '')
					}
				})
			},
			// 处理数据格式计算数据
			dataFormat() {
				let obj = this.vuex_cezhanInfo
				let elect = {}
				elect = obj.celiugan
				elect.cexianlist = obj.celiugan.cexianList
				// 测站
				this.cezhanObj = elect
			},
			// 计算流量
			calculateFlow(nub) {
				// console.log('vls', vls);
				let data = []
				data.push(nub)
				let vls = data
				// console.log('vls---------------', data);
				let vlAll = []
				let vl0 = null //区域流量
				let vl1 = null //区域流量
				let vlz = null //区域流量
				let vln = null //区域流量
				let vln1 = null //区域流量
				let vln2 = null //区域流量

				// 不参与循环
				// cot
				let sin27LL = Math.sin(this.cezhanObj.lSA * Math.PI / 180)
				let cos27LL = Math.cos(this.cezhanObj.lSA * Math.PI / 180)
				let areaLL = cos27LL / sin27LL //三角面积L

				let sin27RR = Math.sin(this.cezhanObj.rSA * Math.PI / 180)
				let cos27RR = Math.cos(this.cezhanObj.rSA * Math.PI / 180)
				let areaRR = cos27RR / sin27RR //三角面积R
				// console.log('****',sin27LL,areaRR);
				// VL0
				vl0 = 0.5 * this.wD * this.wD * areaLL * (vls[0] * 1) * (this.cezhanObj.kL * 1)
				vlAll.push(vl0.toFixed(6) * 1)

				// console.log('vl0', vl0);

				//VL1
				vl1 = 0.5 * [(vls[0] * 1) + (vls[0] * 1)] * (this.wD) * (this.cezhanObj.cexianlist[0].cR * 1)
				vlAll.push(vl1.toFixed(6) * 1)

				// console.log('vl1', vl1);

				// 中间逻辑
				if (vls.length > 1) {
					for (let i = 0; i < vls.length - 1; i++) {
						vlz = 0.5 * [(vls[i] * 1) + (vls[i + 1] * 1)] * (this.wD) * [(this.cezhanObj
							.cexianlist[i + 1].cR * 1) - (this.cezhanObj.cexianlist[i].cR *
							1)]
						vlAll.push(vlz.toFixed(6) * 1)
					}
				}

				//VLN+1
				vln1 = 0.5 * [(vls[vls.length - 1] * 1) + (vls[vls.length - 1] *
					1)] * (this.wD) * [(this
					.cezhanObj.qudikuandu * 1) - (this.cezhanObj.cexianlist[vls.length - 1].cR * 1)]
				vlAll.push(vln1.toFixed(6) * 1)

				// console.log('vln1', vln1, this.cezhanObj.cexianlist);

				//VLN+2
				vln2 = 0.5 * this.wD * this.wD * areaRR * (vls[vls.length - 1] * 1) * (this.cezhanObj.kR * 1)
				vlAll.push(vln2.toFixed(6) * 1)

				// console.log('vln2', vln2);

				// 计算总平均流速
				let vlQitem = []
				let vlQArr = []
				let vlQALL = []

				let sum = 0;
				for (let i = 0; i < vlAll.length; i++) {
					sum += vlAll[i];
				}
				// this.liusliangnub = sum.toFixed(3) * 1
				// console.log('流量数组', vlAll);
				console.log('流量', sum.toFixed(3) * 1);
				return sum.toFixed(3) * 1
			},
			// 蓝牙
			//监听消息变化++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
			listenValueChange(data) {
				let resHex = data
				setTimeout(() => {
					uni.onBLECharacteristicValueChange(res => {
						let resHex = this.ab2hex(res.value)
						console.log('监听数据', resHex, resHex.length);
						// 睿鑫
						if (this.dopBrand == '泰克' && resHex.substr(0, 2) == '65') {
							console.log('ABCD', resHex.substr(6, 8));
							let hexabc = resHex.substr(6, 8)
							let aa = hexabc.substr(0, 2)
							let bb = hexabc.substr(2, 2)
							let cc = hexabc.substr(4, 2)
							let dd = hexabc.substr(6, 2)

							let nubm = aa + bb + cc + dd

							this.mfvFn(this.hexToFloat(nubm).toFixed(3))
							console.log('aa', aa);
							console.log('bb', bb);
							console.log('cc', cc);
							console.log('dd', dd);
							console.log('nubm', nubm);
							console.log('浮点数', this.hexToFloat(nubm).toFixed(3))
						}
						if (this.dopBrand == '大禹' && resHex.substr(0, 2) == '66') {
							console.log('ABCD', resHex.substr(6, 8));
							let hexabc = resHex.substr(6, 8)
							let aa = hexabc.substr(0, 2)
							let bb = hexabc.substr(2, 2)
							let cc = hexabc.substr(4, 2)
							let dd = hexabc.substr(6, 2)

							let nubm = aa + bb + cc + dd

							this.mfvFn(this.hexToFloat(nubm).toFixed(3))
							console.log('aa', aa);
							console.log('bb', bb);
							console.log('cc', cc);
							console.log('dd', dd);
							console.log('nubm', nubm);
							console.log('浮点数', this.hexToFloat(nubm).toFixed(3))
						}
						if (this.dopBrand == '睿鑫' && resHex.substr(0, 2) == '64') {
							console.log('ABCD', resHex.substr(6, 8));
							let hexabc = resHex.substr(6, 8)
							let aa = hexabc.substr(0, 2)
							let bb = hexabc.substr(2, 2)
							let cc = hexabc.substr(4, 2)
							let dd = hexabc.substr(6, 2)

							let nubm = cc + dd + aa + bb

							this.mfvFn(this.hexToFloat(nubm).toFixed(3))
							console.log('aa', aa);
							console.log('bb', bb);
							console.log('cc', cc);
							console.log('dd', dd);
							console.log('nubm', nubm);
							console.log('浮点数', this.hexToFloat(nubm).toFixed(3))
						}
						if (this.dopBrand == '德希' && resHex.substr(0, 2) == '04') {
							// 水深
							let strwd = resHex.substr(18, 4)
							this.deepWaterFn(this.hexToDecimal(strwd) / 1000)
							// 流速
							let str = resHex.substr(14, 4)
							this.mfvFn(this.hexToDecimal(str) / 1000)

						}
					})
				}, 300)
			},
			//数组求平均
			averageSum(arr) {
				if (arr.length === 0) {
					return 0; // 当数组为空时，平均值为0
				}

				let sum = 0;
				for (let i = 0; i < arr.length; i++) {
					sum += arr[i] * 1;
				}

				return sum / arr.length;
			},
			// 删除最小的前面几个数字
			removeSmallestN(arr, n) {
				// 对数组进行升序排序
				const sorted = arr.sort((a, b) => a - b);
				// 删除最前面的n个数字
				sorted.splice(0, n);
				return sorted;
			},
			// 删除最大的后面几个数字
			removeMax(arr, n) {
				// 对数组进行升序排序
				const sorted = arr.sort((a, b) => a - b);
				// 删除最后面的n个数字
				sorted.splice(-n);
				return sorted;
			},
			// 16进制转10进制
			hexToDecimal(hex) {
				return parseInt(hex, 16);
			},
			// 16进制转浮点数
			hexToFloat(hexString) {
				// 去除空格
				hexString = hexString.replace(/\s+/g, '');

				// 检查输入是否有效
				if (!/^[0-9A-Fa-f]{8}$/.test(hexString)) {
					throw new Error('Invalid hex string. Must be 8 characters long.');
				}

				// 将 16 进制字符串转换为字节数组
				const byteArray = new Uint8Array(
					hexString.match(/.{1,2}/g).map(byte => parseInt(byte, 16))
				);

				// 使用 DataView 将字节数组解释为浮点数
				const dataView = new DataView(byteArray.buffer);
				const floatNumber = dataView.getFloat32(0, false); // false 表示大端序

				return floatNumber;
			},
			// ArrayBuffer转16进度字符串示例
			ab2hex(buffer) {
				const hexArr = Array.prototype.map.call(
					new Uint8Array(buffer),
					function(bit) {
						return ('00' + bit.toString(16)).slice(-2)
					}
				)
				return hexArr.join('')
			},
			// 输入蓝牙数据
			conbuffer(data) {
				let msg = data
				// 向蓝牙设备发送一个0x00的16进制数据
				const buffer = new ArrayBuffer(msg.length)
				const dataView = new DataView(buffer)
				// dataView.setUint8(0, 0)
				for (var i = 0; i < msg.length; i++) {
					// dataView.setUint8(i, msg.charAt(i).charCodeAt())
					dataView.setUint8(i, msg[i]);
				}
				this.sendMsgToKey(buffer)
			},
			/* 向设备发送消息(分包发送，单包20字节，递归发送)
			 */
			sendMsgToKey(buffer) {
				var that = this //vue中的this
				const packageSize = 20 //分包大小
				if (buffer.byteLength <= 20) { //如果小于20直接发送，不再继续调用
					uni.writeBLECharacteristicValue({
						// 这里的 deviceId 需要在上面的 getBluetoothDevices 或 onBluetoothDeviceFound 接口中获取
						deviceId: that.deviceId,
						// 这里的 serviceId 需要在上面的 getBLEDeviceServices 接口中获取
						serviceId: that.serviceId,
						// 这里的 characteristicId 需要在上面的 getBLEDeviceCharacteristics 接口中获取
						characteristicId: that.fff, //第二步写入的特征值
						// 这里的value是ArrayBuffer类型
						value: buffer,
						writeType: 'write',
						success: (res) => {
							//此时设备已接收到你写入的数据
							console.log('写入蓝牙');
						},
						fail: (err) => {
							console.log('传输失败', err)
							this.lanname = this.vuex_devicename
						},
						complete: function() {}
					})
				} else { //如果大于20发送完成后继续递归调用
					var newData = buffer.slice(20)
					var writeBuffer = buffer.slice(0, 20)
					uni.writeBLECharacteristicValue({
						// 这里的 deviceId 需要在上面的 getBluetoothDevices 或 onBluetoothDeviceFound 接口中获取
						deviceId: that.deviceId,
						// 这里的 serviceId 需要在上面的 getBLEDeviceServices 接口中获取
						serviceId: that.serviceId,
						// 这里的 characteristicId 需要在上面的 getBLEDeviceCharacteristics 接口中获取
						characteristicId: that.fff, //第二步写入的特征值
						// 这里的value是ArrayBuffer类型
						value: writeBuffer,
						writeType: 'write',
						success: function(res) {
							console.log('写入22222');
							//写入后继续递归调用发送剩下的数据
							setTimeout(() => {
								that.sendMsgToKey(newData)
							}, 100)
						},
						fail: (err) => {
							this.lanname = this.vuex_devicename
							console.log('传输失败', err)
						},
						complete: function() {}
					})
				}
			},
			//获取蓝牙的所有服务
			getBLEDeviceServices() {
				setTimeout(() => {
					uni.getBLEDeviceServices({
						// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
						deviceId: this.vuex_deviceId,
						success: (res) => {
							console.log('获取蓝牙所有服务', res);
							//E95D93AF-251D-470A-A062-FA1922DFA9A8
							//6E400001-B5A3-F393-E0A9-E50E24DCCA9E
							res.services.forEach((item) => {
								if (item.uuid.indexOf("0000FFF0") != -1) {
									this.serviceId = item.uuid;
									//获取特征
									this.getBLEDeviceCharacteristics()
								}
								if (item.uuid.indexOf("0000FFE0") != -1) {
									this.serviceId = item.uuid;
									//获取特征
									this.getBLEDeviceCharacteristics()
								}
								if (item.uuid.indexOf("00001000") != -1) {
									this.serviceId = item.uuid;
									//获取特征
									this.getBLEDeviceCharacteristics()
								}
							})
						}
					})
				}, 1000)
			},
			//获取蓝牙特征
			getBLEDeviceCharacteristics() {
				console.log('获取蓝牙特征值');
				setTimeout(() => {
					uni.getBLEDeviceCharacteristics({
						// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
						deviceId: this.deviceId,
						// 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
						serviceId: this.serviceId,
						success: (res) => {
							this.characteristics = res.characteristics
							res.characteristics.forEach((item) => {

								if (item.uuid.indexOf("FFF2") != -1) {
									this.fff = item.uuid

								}
								if (item.uuid.indexOf("FFE1") != -1) {
									this.fff = item.uuid
								}
								if (item.uuid.indexOf("0000FFE1") != -1) {

									this.characteristicId = item.uuid
									//利用传参的形势传给下面的notify，这里的uuid如果都需要用到，就不用做判断了，建议使用setTimeout进行间隔性的调用此方法
									this.notifyBLECharacteristicValueChange(item.uuid)
								}
								if (item.uuid.indexOf("0000FFF1") != -1) {
									this.characteristicId = item.uuid
									this.notifyBLECharacteristicValueChange(item.uuid)
								}
								// EW-DTU02
								if (item.uuid.indexOf("00001001") != -1) {
									this.fff = item.uuid
								}
								if (item.uuid.indexOf("00001002") != -1) {
									this.characteristicId = item.uuid
									this.notifyBLECharacteristicValueChange(item.uuid)
								}
							})
						},
						fail: (res) => {
							console.log(res)
						}
					})
				}, 1000)
			},
			// 启用 notify 功能
			notifyBLECharacteristicValueChange(characteristicId) {
				console.log('启用 notify 功能');
				uni.notifyBLECharacteristicValueChange({
					state: true, // 启用 notify 功能
					// 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
					deviceId: this.deviceId,

					// 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
					serviceId: this.serviceId,
					// 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
					characteristicId: this.characteristicId,
					success: (res) => {
						console.log('蓝牙名字', res);
						// vuex
						// uni.$u.vuex('vuex_devicename', this.vuexlist.name)
						uni.hideLoading()
						this.listenValueChange()
						uni.showToast({
							title: '设备已连接',
							mask: true,
							duration: 1000
						});
						console.log('蓝牙服务已开启');
					},
					fail: (res) => {
						uni.hideLoading()
						uni.showToast({
							title: '连接设备失败',
							icon: 'fail',
							mask: true,
							duration: 1000
						});

					}
				})
			},
			// 求和
			sum(arr) {
				var sum = 0;
				for (var i = 0; i < arr.length; i++) {
					sum += arr[i]
				}
				return sum
			},
		},

		/**
		 * 组件销毁前生命周期钩子
		 * 用于清理定时器，防止内存泄漏
		 */
		beforeDestroy() {
			if (this.measureInterval) {
				clearInterval(this.measureInterval);
			}
		},

	};
</script>

<style lang="scss">
	// 弹窗
	.popbox {
		.popit {
			display: flex;
			justify-content: space-between;
			align-items: center;
			margin: 10rpx 0;

			.tex {
				font-size: 35rpx;
				margin-right: 20rpx;
			}

			.bga {
				width: 250rpx;
				border-radius: 10rpx;
				padding: 10rpx 0;
				text-align: center;
			}

			.inpa {
				width: 250rpx;
				color: #ffffff;
				border-radius: 10rpx;
				padding: 10rpx 0;
				margin-bottom: 10rpx;
				text-align: center;
				background-color: #bd0000;

				&:active {
					background-color: rgba(0, 0, 0, 0.2);
				}
			}

			.inpb {
				width: 250rpx;
				color: #ffffff;
				border-radius: 10rpx;
				padding: 10rpx 0;
				text-align: center;
				margin-bottom: 10rpx;
				background-color: #00b457;

				&:active {
					background-color: rgba(0, 0, 0, 0.2);
				}
			}
		}
	}

	// 主容器样式
	.flow-measurement {
		padding: 20rpx;
		background: #f0f5ff;
		min-height: 100vh;
		box-sizing: border-box;

		// 标题区域样式
		.header {
			text-align: center;
			margin-bottom: 25px;
			padding: 25px 0;
			background: linear-gradient(135deg, #4b6cb7 0%, #182848 100%);
			border-radius: 16px;
			color: white;
			box-shadow: 0 6px 18px rgba(0, 0, 0, 0.12);

			// 主标题样式
			h1 {
				font-size: 36rpx;
				font-weight: bold;
				margin-bottom: 10rpx;
			}

			// 副标题样式
			.subtitle {
				font-size: 26rpx;
				opacity: 0.9;
			}
		}

		// 卡片通用样式
		.card {
			background-color: #fff;
			border-radius: 20rpx;
			padding: 20rpx;
			margin-bottom: 20rpx;
			box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.06);

			// 统计卡片特定样式
			&.stats-card {
				.stats-row {
					display: flex;
					justify-content: space-between;
					margin-bottom: 20rpx;

					// 统计项样式
					.stat-item {
						flex: 1;
						text-align: center;
						padding: 20rpx;
						background: #f9faff;
						border-radius: 16rpx;
						margin: 0 10rpx;

						// 统计值样式
						.stat-value {
							font-size: 40rpx;
							font-weight: bold;
							color: #2979ff;
							margin-bottom: 12rpx;
						}

						// 统计标签样式
						.stat-label {
							font-size: 28rpx;
							color: #666;
						}
					}
				}
			}


		}

		// 图表卡片特定样式
		.chart-card {
			background-color: #fff;
			border-radius: 20rpx;
			margin-bottom: 20rpx;
			box-shadow: 0 8rpx 24rpx rgba(0, 0, 0, 0.06);

			// 图表容器样式 链接
			.chart-container {
				text-align: center;
				height: 250rpx;

				// border-radius: 16rpx;
				// border: 2rpx dashed #ddd;
			}
		}

		.yuan_b {
			text-align: center;
			font-size: 35rpx;
			font-weight: bold;
			margin-bottom: 10rpx;
			color: #00b457;
		}

		.yuan_c {
			text-align: center;
			font-size: 35rpx;
			font-weight: bold;
			margin-bottom: 10rpx;
			color: #000000;
		}

		// 按钮容器样式
		.button-container {
			.button-row {
				display: flex;
				justify-content: space-between;
				margin-top: 20rpx;

				// 按钮通用样式
				.btn {
					flex: 1;
					padding: 28rpx 0;
					border-radius: 16rpx;
					text-align: center;
					font-size: 32rpx;
					font-weight: bold;
					margin: 0 20rpx;
					display: flex;
					align-items: center;
					justify-content: center;
					box-shadow: 0 6rpx 12rpx rgba(0, 0, 0, 0.1);
					transition: all 0.2s ease;

					// 按钮点击效果
					&:active {
						transform: translateY(4rpx);
						box-shadow: 0 2rpx 6rpx rgba(0, 0, 0, 0.1);
					}

					// 开始按钮样式
					&.btn-start {
						background: linear-gradient(135deg, #4CAF50 0%, #2E7D32 100%);
						color: white;
					}

					// 停止按钮样式
					&.btn-stop {
						background: linear-gradient(135deg, #f44336 0%, #c62828 100%);
						color: white;
					}

					// 清空按钮样式
					&.btn-clear {
						background: linear-gradient(135deg, #9e9e9e 0%, #616161 100%);
						color: white;
					}

					// 按钮文本样式
					.btn-text {
						margin-right: 15rpx;
					}

					// 按钮图标样式
					.btn-icon {
						font-size: 36rpx;
					}
				}
			}
		}

		// 状态指示器样式
		.status-indicator {
			display: flex;
			align-items: center;
			justify-content: center;
			margin: 20rpx 0;
			padding: 20rpx;
			background: #fff;
			border-radius: 16rpx;
			box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.06);

			// 状态点样式
			.status-dot {
				width: 24rpx;
				height: 24rpx;
				border-radius: 50%;
				background: #f44336;
				margin-right: 15rpx;
				transition: background 0.3s ease;
			}

			// 状态文本样式
			.status-text {
				font-size: 28rpx;
				color: #666;
			}

			// 活动状态样式
			&.active {
				.status-dot {
					background: #4CAF50;
					animation: pulse 1.5s infinite;
				}
			}
		}
	}

	// 状态点脉冲动画
	@keyframes pulse {
		0% {
			opacity: 1;
		}

		50% {
			opacity: 0.5;
		}

		100% {
			opacity: 1;
		}
	}
</style>